package com.jzo2o.foundations.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.foundations.constants.RedisConstants;
import com.jzo2o.foundations.enums.FoundationStatusEnum;
import com.jzo2o.foundations.mapper.*;
import com.jzo2o.foundations.model.domain.*;
import com.jzo2o.foundations.model.dto.request.ServePageQueryReqDTO;
import com.jzo2o.foundations.model.dto.request.ServeUpsertReqDTO;
import com.jzo2o.foundations.model.dto.response.ServeResDTO;
import com.jzo2o.foundations.service.IServeService;
import com.jzo2o.mysql.utils.PageHelperUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ServeServiceImpl extends ServiceImpl<ServeMapper, Serve> implements IServeService {
    @Resource
    private ServeItemMapper serveItemMapper;

    @Resource
    private RegionMapper regionMapper;

    @Autowired
    private ServeSyncMapper serveSyncMapper;

    @Autowired
    private ServeTypeMapper serveTypeMapper;

    @Override
    @Cacheable(value = RedisConstants.CacheName.SERVE, key = "#id",cacheManager = RedisConstants.CacheManager.ONE_DAY)
    public Serve queryServeByIdCache(Long id) {
        return getById(id);
    }

    /**
     * 根据ID查询服务详情信息
     * @param id
     * @return
     */
    @Override
    public ServeAggregationResDTO findServeDetailById(Long id) {
        return baseMapper.findServeDetailById(id);
    }

    /**
     * 分页查询服务列表
     * @param servePageQueryReqDTO 查询条件
     * @return 分页列表
     */
    @Override
    public PageResult<ServeResDTO> page(@RequestBody ServePageQueryReqDTO servePageQueryReqDTO) {
        //调用mapper查询数据，这里由于继承了ServiceImpl<ServeMapper, Serve>，使用baseMapper相当于使用ServeMapper
        PageResult<ServeResDTO> serveResDTOPageResult = PageHelperUtils.selectPage(servePageQueryReqDTO, () -> baseMapper.queryServeListByRegionId(servePageQueryReqDTO.getRegionId()));
        return serveResDTOPageResult;
    }

    /**
     * 批量新增
     * @param serveUpsertReqDTOList 新增数据
     */

    @Override
    @Transactional
    public void batchAdd(List<ServeUpsertReqDTO> serveUpsertReqDTOList) {
        // 批量查询服务项
        List<Long> serveItemIds = serveUpsertReqDTOList.stream()
                .map(ServeUpsertReqDTO::getServeItemId)
                .collect(Collectors.toList());
        List<ServeItem> serveItems = serveItemMapper.selectBatchIds(serveItemIds);
        //Map是用来存储key-value键值对的，其中key不可以重复，value可以重复
        Map<Long, ServeItem> serveItemMap = serveItems.stream()
                .collect(Collectors.toMap(ServeItem::getId, item -> item));

        // 过滤出未启用的服务项
        List<ServeItem> invalidServeItems = serveUpsertReqDTOList.stream()
                .map(dto -> serveItemMap.get(dto.getServeItemId()))
                .filter(item -> ObjectUtil.isNull(item) || item.getActiveStatus() != FoundationStatusEnum.ENABLE.getStatus())
                .collect(Collectors.toList());

        if (!invalidServeItems.isEmpty()) {
            throw new ForbiddenOperationException("存在未启用的服务项，无法添加到区域下使用");
        }

        // 批量查询现有服务
        List<Long> regionIds = serveUpsertReqDTOList.stream()
                .map(ServeUpsertReqDTO::getRegionId)
                .collect(Collectors.toList());
        List<Serve> existingServes = lambdaQuery()
                .in(Serve::getRegionId, regionIds)
                .in(Serve::getServeItemId, serveItemIds)
                .list();

        Map<Long, List<Serve>> existingServeMap = existingServes.stream()
                .collect(Collectors.groupingBy(Serve::getRegionId));

        // 过滤出重复的服务项
        List<ServeUpsertReqDTO> duplicateServeItems = serveUpsertReqDTOList.stream()
                .filter(dto -> existingServeMap.getOrDefault(dto.getRegionId(), List.of()).stream()
                        .anyMatch(serve -> serve.getServeItemId().equals(dto.getServeItemId())))
                .collect(Collectors.toList());

        if (!duplicateServeItems.isEmpty()) {
            ServeItem serveItem = serveItemMap.get(duplicateServeItems.get(0).getServeItemId());
            throw new ForbiddenOperationException(serveItem.getName() + "服务已存在");
        }

        // 批量新增服务
        List<Serve> servesToAdd = serveUpsertReqDTOList.stream()
                .map(dto -> {
                    Serve serve = BeanUtil.toBean(dto, Serve.class);
                    Region region = regionMapper.selectById(dto.getRegionId());
                    serve.setCityCode(region.getCityCode());
                    return serve;
                })
                .collect(Collectors.toList());

        saveBatch(servesToAdd);
    }

//    @Override
//    public void batchAdd(List<ServeUpsertReqDTO> serveUpsertReqDTOS) {
//
//        for (ServeUpsertReqDTO reqDTO : serveUpsertReqDTOS) {
//            //1.校验服务项是否为启用状态，不是启用状态不能新增
//            ServeItem serveItem = serveItemMapper.selectById(reqDTO.getServeItemId());
//            if (serveItem.getActiveStatus() != FoundationStatusEnum.ENABLE.getStatus() || ObjectUtil.isNull(serveItem)) {
//                throw new ForbiddenOperationException("服务项未启用，不能新增服务");
//            }
//
//            //2.判断服务是否重复，如果重复，则抛出异常
//            Integer count = lambdaQuery()
//                    .eq(Serve::getServeItemId, reqDTO.getServeItemId())
//                    .eq(Serve::getRegionId, reqDTO.getRegionId())
//                    .count();
//            if (count > 0) {
//                throw new ForbiddenOperationException("服务已存在，不能重复新增");
//            }

//
//            //3.保存到serve数据库
//            Serve serve = BeanUtil.toBean(reqDTO, Serve.class);
//            Region region = regionMapper.selectById(reqDTO.getRegionId());
//            serve.setCityCode(region.getCityCode());
//            baseMapper.insert(serve);
//        }
//    }


    /**
     * 更新服务价格
     * */
    @Override
    @Transactional
    public Serve update(Long id, BigDecimal price) {
        //1.更新服务价格
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getPrice, price)
                .update();
        if(!update){
            throw new CommonException("修改服务价格失败");
        }
        return baseMapper.selectById(id);
    }

    /**
     * 修改服务上架状态
     *
     * */
    @Override
    @Transactional
    @CachePut(value = RedisConstants.CacheName.SERVE, key = "#id",  cacheManager = RedisConstants.CacheManager.ONE_DAY)
    public Serve onSale(Long id){
        //查询服务
        Serve serve = baseMapper.selectById(id);
        //服务不存在
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //上架状态
        Integer saleStatus = serve.getSaleStatus();
        //草稿或下架状态方可上架
        if (!(saleStatus==FoundationStatusEnum.INIT.getStatus() || saleStatus==FoundationStatusEnum.DISABLE.getStatus())) {
            throw new ForbiddenOperationException("草稿或下架状态方可上架");
        }
        //服务项id
        Long serveItemId = serve.getServeItemId();   //服务项id
        ServeItem serveItem = serveItemMapper.selectById(serveItemId);
        if(ObjectUtil.isNull(serveItem)){
            throw new ForbiddenOperationException("所属服务项不存在");
        }
        //服务项的启用状态
        Integer activeStatus = serveItem.getActiveStatus();
        //服务项为启用状态方可上架
        if (!(FoundationStatusEnum.ENABLE.getStatus()==activeStatus)) {
            throw new ForbiddenOperationException("服务项为启用状态方可上架");
        }

        //更新上架状态
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getSaleStatus, FoundationStatusEnum.ENABLE.getStatus())
                .update();
        if(!update){
            throw new CommonException("启动服务失败");
        }

        //添加同步表
        addServeSync(id);
        return baseMapper.selectById(id);
    }

    /**
     * 修改服务下架状态
     * */
    @Override
    @CacheEvict(value = RedisConstants.CacheName.SERVE_ICON, key = "#id")
    public Serve offSale(Long id) {
        //查询服务
        Serve serve = baseMapper.selectById(id);
        //服务不存在
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //下架状态
        Integer saleStatus = serve.getSaleStatus();
        //上架状态方可下架
        if (!(saleStatus==FoundationStatusEnum.ENABLE.getStatus())) {
            throw new ForbiddenOperationException("上架状态方可下架");
        }

        //更新下架状态
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getSaleStatus, FoundationStatusEnum.DISABLE.getStatus())
                .update();
        if(!update){
            throw new CommonException("下架服务失败");
        }
        //返回服务
        serveSyncMapper.deleteById(id);
        return baseMapper.selectById(id);
    }

    /**
     * 设置热门
     * */
    @Override
    public void onHot(Long id) {
        //查询服务
        Serve serve = baseMapper.selectById(id);
        //服务不存在
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //热门状态
        Integer hotStatus = serve.getIsHot();
        //非热门状态方可设置热门
        if (!hotStatus.equals(0)) {
            throw new ForbiddenOperationException("非热门状态方可设置热门");
        }
        //更新热门状态
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getIsHot, 1)
                .update();
        if(!update){
            throw new CommonException("设置热门服务失败");
        }
//        baseMapper.selectById(id);

    }

    /**
     * 取消热门
     * */
    @Override
    public void offHot(Long id) {
        //查询服务
        Serve serve = baseMapper.selectById(id);
        //服务不存在
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //热门状态
        Integer hotStatus = serve.getIsHot();
        //热门状态方可取消热门
        if (!hotStatus.equals(1)) {
            throw new ForbiddenOperationException("热门状态方可取消热门");
        }
        //更新热门状态
        boolean update = lambdaUpdate()
                .eq(Serve::getId, id)
                .set(Serve::getIsHot, 0)
                .update();
        if(!update){
            throw new CommonException("取消热门服务失败");
        }
        baseMapper.selectById(id);
    }

    @Override
    public void delete(Long id) {
        //查询服务
        Serve serve = baseMapper.selectById(id);
        //服务不存在
        if(ObjectUtil.isNull(serve)){
            throw new ForbiddenOperationException("区域服务不存在");
        }
        //删除校验：只有草稿状态方可删除
        if (!(FoundationStatusEnum.INIT.getStatus() == serve.getSaleStatus())) {
            throw new ForbiddenOperationException("只有草稿状态方可删除");
        }
        //删除服务
        baseMapper.deleteById(id);
    }

    /**
     * 新增服务同步数据
     *
     * @param serveId 服务id
     */
    private void addServeSync(Long serveId) {
        //服务信息
        Serve serve = baseMapper.selectById(serveId);
        //区域信息
        Region region = regionMapper.selectById(serve.getRegionId());
        //服务项信息
        ServeItem serveItem = serveItemMapper.selectById(serve.getServeItemId());
        //服务类型
        ServeType serveType = serveTypeMapper.selectById(serveItem.getServeTypeId());

        ServeSync serveSync = new ServeSync();
        serveSync.setServeTypeId(serveType.getId());
        serveSync.setServeTypeName(serveType.getName());
        serveSync.setServeTypeIcon(serveType.getServeTypeIcon());
        serveSync.setServeTypeImg(serveType.getImg());
        serveSync.setServeTypeSortNum(serveType.getSortNum());

        serveSync.setServeItemId(serveItem.getId());
        serveSync.setServeItemIcon(serveItem.getServeItemIcon());
        serveSync.setServeItemName(serveItem.getName());
        serveSync.setServeItemImg(serveItem.getImg());
        serveSync.setServeItemSortNum(serveItem.getSortNum());
        serveSync.setUnit(serveItem.getUnit());
        serveSync.setDetailImg(serveItem.getDetailImg());
        serveSync.setPrice(serve.getPrice());

        serveSync.setCityCode(region.getCityCode());
        serveSync.setId(serve.getId());
        serveSync.setIsHot(serve.getIsHot());
        serveSyncMapper.insert(serveSync);
    }
}